﻿using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using NuGet.Packaging;
using NuGet.Protocol.Core.Types;
using NuGet.Versioning;
using QuickGet.Core.Services;
using QuickGet.Core.Stores;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace QuickGet.Core
{
    public record DownloadPackageCommand(string PackageId, string PackageVersion, string PackageSourceName);

    public class DownloadPackage : NugetOperationBase
    {
        protected virtual IOptions<QuickGetOptions> _options { get; set; }
        protected virtual IPackageStore _packageStore { get; set; }

        public DownloadPackage(
            ILogger<DownloadPackage> logger, 
            SourceCacheContext sourceCache, 
            INugetResourceResolver nugetResourceResolver, 
            INugetSourceRepositoryResolver nugetSourceRepositoryResolver,
            IOptions<QuickGetOptions> options,
            IPackageStore packageStore) 
            : base(
                  logger, 
                  sourceCache, 
                  nugetResourceResolver, 
                  nugetSourceRepositoryResolver)
        {
            _options = options;
            _packageStore = packageStore;
        }

        public async Task ExecuteAsync(DownloadPackageCommand command, CancellationToken cancellationToken)
        {
            var resource = await _resourceResolver.GetResourceAsync<FindPackageByIdResource>(command.PackageSourceName, cancellationToken);

            if (resource is null) { return; }

            var folderPath = PrepareSavePath(command.PackageId, command.PackageVersion);
            var filePath = Path.Combine(folderPath, _packageStore.GetPackageFileName(command.PackageId, command.PackageVersion));

            var packageVersion = new NuGetVersion(command.PackageVersion);

            using var fs = new FileStream(filePath, FileMode.OpenOrCreate);

            await resource.CopyNupkgToStreamAsync(
                command.PackageId,
                packageVersion,
                fs,
                _sourceCache,
                _nugetLogger,
                cancellationToken);

            await _packageStore.SaveAsync(command.PackageId, cancellationToken);
            await _packageStore.SaveDownloadAsync(command.PackageId, command.PackageVersion, folderPath, cancellationToken);

            using var packageReader = new PackageArchiveReader(fs);
            var nuspecReader = await packageReader.GetNuspecReaderAsync(cancellationToken);
        }

        private string PrepareSavePath(string packageId, string packageVersion)
        {
            var path = _packageStore.BuildPackageSavePath(packageId, packageVersion);

            if(Directory.Exists(path) == false)
            {
                Directory.CreateDirectory(path);
            }

            return path;
        }
    }
}
